import 'dart:async';
import 'dart:io';

import 'package:ac/common/ac_more_util.dart';
import 'package:ac/common/ac_translation_util.dart';
import 'package:ac/data/ac_app_preferences.dart';
import 'package:ac/data/ac_user_manager.dart';
import 'package:ac/page/ac_message/ac_message_logic.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart';
import 'package:flutter_sound/flutter_sound.dart';

import 'ac_chat_state.dart';

class AcChatLogic extends GetxController {
  final AcChatState state = AcChatState();
  late final AcMoreUtil moreUtil;

  AcMessageLogic get messageLogic => Get.find<AcMessageLogic>();

  RCIMIWEngine? get engine => messageLogic.engine;

  FlutterSoundRecorder recorderModule = FlutterSoundRecorder();
  FlutterSoundPlayer playerModule = FlutterSoundPlayer();
  StreamSubscription<RecordingDisposition>? _recorderSubscription;

  Timer? recordTimer; // 计时器，用来控制录音时长;

  List voicePlayList = []; //用来控制语音播放列表

  String voicePath = ""; //临时储存语音文件路径

  @override
  void onInit() {
    // TODO: implement onInit
    super.onInit();
    state.conversation.value = Get.arguments['conversation'];
    moreUtil = AcMoreUtil(
        state.conversation.value!.userinfo, state.conversation.refresh,
        blockCallback: () {
      Get.back();
    });

    messageLogic.addOnReceiveMessageListener(_onMessageReceive);
    messageLogic.addOnMessageAttachedListener(_onMessageAttached);
    messageLogic.addOnMessageSentListener(_onMessageSend);
    messageLogic.addOnMediaMessageAttachedListener(_onMessageAttached);
    messageLogic.addOnMediaMessageSendingListener(_onMediaMessageSending);
    _initializeSound();
    _loadMessages();
  }

  @override
  Future<void> onClose() async {
    // TODO: implement dispose
    messageLogic.removeOnReceiveMessageListener(_onMessageReceive);
    messageLogic.removeOnMessageAttachedListener(_onMessageAttached);
    messageLogic.removeOnMessageSentListener(_onMessageSend);
    messageLogic.removeOnMediaMessageAttachedListener(_onMessageAttached);
    messageLogic.removeOnMediaMessageSendingListener(_onMediaMessageSending);
    try {
      await playerModule.closeAudioSession();
      await recorderModule.closeAudioSession();
    } catch (e) {
      debugPrint('closeAudioSession error: $e');
    }
    super.onClose();
  }

  void _loadMessages() async {
    IRCIMIWGetMessagesCallback? callback = IRCIMIWGetMessagesCallback(
        onSuccess: (List<RCIMIWMessage>? t) {
          if (t != null) {
            state.messages.addAll(t);
            for (var message in state.messages) {
              if (message is RCIMIWTextMessage) {
                if (AcAppPreferences.instance.getAutoTranslate() &&
                    message.senderUserId !=
                        AcUserManager.userInfoModel?.userInfo.userId) {
                  translation(message);
                }
              } else if (message is RCIMIWMediaMessage) {
                engine?.downloadMediaMessage(message);
              }
            }
          }
          if (state.conversation.value?.conversation?.unreadCount != 0) {
            _cleanUnreadCount();
          }
        },
        onError: (int? code) {});

    await engine?.getMessages(
        RCIMIWConversationType.private,
        state.conversation.value!.userinfo.userId!,
        null,
        0,
        RCIMIWTimeOrder.before,
        RCIMIWMessageOperationPolicy.localRemote,
        20,
        callback: callback);
  }

  void _cleanUnreadCount() {
    engine?.clearUnreadCount(
      RCIMIWConversationType.private,
      state.conversation.value!.userinfo.userId!,
      null,
      state.messages.first.sentTime!,
    );
    messageLogic.initConversationList();
  }

  void sendTextMsg() async {
    if (state.inputController.text.isEmpty) {
      return;
    }
    RCIMIWTextMessage? message = await engine?.createTextMessage(
      RCIMIWConversationType.private,
      state.conversation.value!.userinfo.userId!,
      null,
      state.inputController.text,
    );
    state.inputController.text = "";
    await engine?.sendMessage(message as RCIMIWMessage);
  }

  void sendImageMsg() async {
    PermissionStatus status = await Permission.photos.request();
    if (!status.isGranted) {
      EasyLoading.showToast("You have not authorised this permission.");
      return;
    }
    final ImagePicker picker = ImagePicker();
    final XFile? image = await picker.pickImage(source: ImageSource.gallery);
    if (image == null) {
      return;
    }
    RCIMIWImageMessage? message = await engine?.createImageMessage(
      RCIMIWConversationType.private,
      state.conversation.value!.userinfo.userId!,
      null,
      image.path,
    );
    await engine?.sendMediaMessage(message as RCIMIWMediaMessage);
  }

  Future<void> sendVoiceMsg() async {
    RCIMIWVoiceMessage? message = await engine?.createVoiceMessage(
        RCIMIWConversationType.private,
        state.conversation.value!.userinfo.userId!,
        null,
        voicePath,
        state.timeSecond.value);
    await engine?.sendMediaMessage(message as RCIMIWMediaMessage);
  }

  /// 开始录音
  void startRecorder() async {
    try {
      state.voicing.value = true;
      PermissionStatus status = await Permission.microphone.request();
      debugPrint('===>  startRecorder status: $status');
      if (!status.isGranted) {
        EasyLoading.showToast("You have not authorised this permission.");
        throw RecordingPermissionException("don't have permission");
      }
      Directory tempDir = await getTemporaryDirectory();
      var time = DateTime.now().millisecondsSinceEpoch;
      String path = '${tempDir.path}/voice-$time${ext[Codec.aacADTS.index]}';
      debugPrint('===>  startRecorder path: $path');

      /// 监听录音
      await recorderModule.startRecorder(
        toFile: path,
        codec: Codec.aacADTS,
      );
      debugPrint('===>  startRecorder success');
      _recorderSubscription = recorderModule.onProgress?.listen((e) {
        DateTime date = DateTime.fromMillisecondsSinceEpoch(
            e.duration.inMilliseconds,
            isUtc: true);
        state.timeSecond.value = e.duration.inSeconds;
        if (date.second >= 60) {
          stopRecorder();
        }
      });

      voicePath = path;
    } catch (err) {
      debugPrint('startRecorder error: $err');
      stopRecorder();
    }
  }

  Future<void> stopRecorder() async {
    try {
      await recorderModule.stopRecorder();
      if(state.voiceValid.value == false){
        return;
      }
      if(voicePath.isEmpty){
        return;
      }
      Duration? duration = await flutterSoundHelper.duration(voicePath);
      var s = duration != null ? duration.inMilliseconds / 1000 : 0;
      if (s > 1) {
        await sendVoiceMsg();
      } else {
        EasyLoading.showToast("Recording cannot be less than 1s");
      }
    } catch (err) {
      debugPrint('stopRecorder error: $err');
    } finally {
      _recorderSubscription?.cancel();
      _recorderSubscription = null;
      voicePath = "";
      state.timeSecond.value = 0;
      state.voicing.value = false;
      state.voiceValid.value = true;
    }
  }

  void _onMessageSend(RCIMIWMessage message) {
    var index = state.messages
        .indexWhere((element) => element.messageId == message.messageId);
    if (index != -1) {
      state.messages[index] = message;
    }
  }

  void _onMessageReceive(RCIMIWMessage message) {
    if (message.conversationType == RCIMIWConversationType.private &&
        message.targetId == state.conversation.value!.userinfo.userId) {
      state.messages.insert(0, message);
      _cleanUnreadCount();
      if (AcAppPreferences.instance.getAutoTranslate() &&
          message.senderUserId !=
              AcUserManager.userInfoModel?.userInfo.userId) {
        if (message is RCIMIWTextMessage) {
          translation(message);
        }
      }
    }
  }

  void _onMessageAttached(RCIMIWMessage message) {
    state.messages.insert(0, message);
    messageLogic.initConversationList();
  }

  Future<void> translation(RCIMIWTextMessage message) async {
    message.expansion ??= {};
    var record = AcAppPreferences.instance.getTranslateRecord(message.text!);
    if (record != null) {
      message.expansion!['translationStatus'] = 2;
      message.extra = record;
      state.messages.refresh();
      return;
    }
    message.expansion!['translationStatus'] = 1;
    state.messages.refresh();
    var translationText = await AcTranslationUtil.translation(message.text!);
    message.expansion!['translationStatus'] = 2;
    message.extra = translationText;
    state.messages.refresh();
    AcAppPreferences.instance
        .setTranslateRecord(message.text!, translationText);
  }

  void _onMediaMessageSending(RCIMIWMessage message, int progress) {
    message.expansion = {"progress": progress};
    var index = state.messages
        .indexWhere((element) => element.messageId == message.messageId);
    if (index != -1) {
      state.messages[index] = message;
      state.messages.refresh();
    }
  }


  Future<void> _initializeSound() async {
    recorderModule.openAudioSession(
      focus: AudioFocus.requestFocusTransient,
      category: SessionCategory.playAndRecord,
      mode: SessionMode.modeDefault,
      device: AudioDevice.speaker,
    );
    await playerModule.closeAudioSession();

    await playerModule.openAudioSession(
      focus: AudioFocus.requestFocusTransient,
      category: SessionCategory.playAndRecord,
      mode: SessionMode.modeDefault,
      device: AudioDevice.speaker,
    );

    await playerModule
        .setSubscriptionDuration(const Duration(milliseconds: 50));
    await recorderModule
        .setSubscriptionDuration(const Duration(milliseconds: 50));
  }

  void clickMessage(RCIMIWVoiceMessage message) {
    playerModule.startPlayer(
      fromURI: message.remote ?? message.local,
      whenFinished: () {
      },
    );
  }
}
